package com.xinlong.shop.framework.security.filter;

import com.xinlong.shop.framework.core.entity.SysMenu;
import com.xinlong.shop.framework.core.entity.SysRole;
import com.xinlong.shop.framework.service.ISysMenuService;
import com.xinlong.shop.framework.service.ISysRoleService;
import com.xinlong.shop.framework.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Pattern;

/**
 * @Author Sylow
 * @Description Url权限过滤
 * @Date: Created in 22:02 2022/5/31
 */
@Component
public class UrlFilterInvocationSecurityMetadataSource implements FilterInvocationSecurityMetadataSource {

    private static final Logger logger = LoggerFactory.getLogger(UrlFilterInvocationSecurityMetadataSource.class);

    private final ISysMenuService sysMenuService;

    private final ISysRoleService sysRoleService;

    public UrlFilterInvocationSecurityMetadataSource(ISysMenuService sysMenuService, ISysRoleService sysRoleService) {
        this.sysMenuService = sysMenuService;
        this.sysRoleService = sysRoleService;
    }

    @Override
    public Collection<ConfigAttribute> getAttributes(Object o) throws IllegalArgumentException {
        Set<ConfigAttribute> set = new HashSet<>();
        // 得到请求地址
        String requestUrl  = ((FilterInvocation) o).getRequest().getRequestURI();

        // 买家会员权限
        if (requestUrl.startsWith("/buyer")) {
            return SecurityConfig.createList("ROLE_BUYER");
        }

        // 通用权限判断
        if (checkPermission(requestUrl)) {
            return SecurityConfig.createList("ROLE_COMMON");
        }

        List<SysMenu> allMenus = sysMenuService.findAllMenus();

        String permission = "";

        // 这里是把当前请求的url和菜单中的匹配，然后用菜单中的url 去寻找到权限
        // 待优化
        for(SysMenu menu : allMenus) {
            if (menu.getPermission() == null) {
                continue;
            }
            boolean result = Pattern.matches(menu.getPermission(),requestUrl);
            if (result) {
                // 通过权限正则url找到权限后，传递该菜单的标识过去，这里虽然名字一样，但是传递的是菜单标识
                permission = menu.getIdentity();
            }
        }


        if (!StringUtil.isEmpty(permission)) {
            // 找出权限
            List<SysRole> roles = sysRoleService.findRolesByPermission(permission);
            if (!CollectionUtils.isEmpty(roles)) {
                roles.forEach(role -> {
                    SecurityConfig securityConfig = new SecurityConfig(role.getAuthority());
                    set.add(securityConfig);
                });
            } else {
                // 默认超级管理员才有
                return SecurityConfig.createList("ROLE_SUPER_ADMIN");
            }
        } else {
            // 默认超级管理员才有
            return SecurityConfig.createList("ROLE_SUPER_ADMIN");
        }

        return set;
    }

    /**
     * 通用权限检查
     * @param url
     * @return
     */
    private boolean checkPermission(String url) {

        if ("/sys/admin/info".equals(url)) {
            return true;
        }
        // 页面访问统计API用的地方比较多  放在通用里
        if (url.startsWith("/sys/page-statistics")){
            return true;
        }

        if ("/uploader".equals(url)) {
            return true;
        }

        // 测试
        if ("/promotion/put-sale-order/testPay".equals(url)) {
            return true;
        }

        return false;
    }


//    private boolean matchUrl(List<String> patternList, String url) {
//        // 遍历url
//        for(String exp : patternList) {
//            boolean result = Pattern.matches(exp,url);
//            return result;
//        }
//        return false;
//    }

    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

    @Override
    public boolean supports(Class<?> aClass) {
        return FilterInvocation.class.isAssignableFrom(aClass);
    }

    public static void main(String[] args) {
        System.out.println(Pattern.matches("/sys/gen/baseGen.*","/sys/gen/baseGen?test=111"));
    }
}
